﻿using Common.Http;
using CToolsWin.BLL;
using CToolsWin.IBLL;
using CToolsWin.Model;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace CToolsWin.Network
{
    public partial class Crawler : Form
    {
        private int AddHeaderTimes = 0;
        private int AddParamTimes = 0;
        public Crawler()
        {
            InitializeComponent();
        }
        #region 公用方法
        public static void StartCrawler(IGrab iGrab, string title)
        {
            Console.WriteLine("请输入Y/N进行{0}数据表初始化确认！", title);
            Console.WriteLine("Y 删除{0}表然后重新创建，然后抓取{0}数据，N（或者其他）跳过", title);
            string input = Console.ReadLine();
            if (input.Equals("Y", StringComparison.OrdinalIgnoreCase))
            {
                //初始化数据
                iGrab.InitTable();
            }
            else
            {
                Console.WriteLine("你选择不初始化{0}数据", title);
            }
            Console.WriteLine("*****************^_^**********************");
        }
        #endregion

        private void btnJDAddress_Click(object sender, EventArgs e)
        {
            StartCrawler(new GrabAddress(), "地址");
        }

        private void btnITellYou_Click(object sender, EventArgs e)
        {
            StartCrawler(new BLLITellYouCategory(), "ITellYou类别");
            StartCrawler(new BLLITellYouResource(), "ITellYou资源");
        }

        private void SaveType_Click(object sender, EventArgs e)
        {
            if (rdoSaveDB.Checked)
            {

            }
            else
            {

            }
        }

        private void AddTextBox(ref int times, TabPage tabPage, string txtKey, int startLocation)
        {
            times++;
            AddTextBoxControl(times, tabPage, txtKey + times + "Key", 135, 9, startLocation + times * 27);
            AddTextBoxControl(times, tabPage, txtKey + times + "Value", 350, 150, startLocation + times * 27);
        }

        private void AddTextBoxControl(int times, TabPage tabPage, string txtName, int width, int localLeft, int localTop)
        {
            TextBox txtBoxKey = new TextBox();

            tabPage.Controls.Add(txtBoxKey);

            txtBoxKey.Location = new System.Drawing.Point(localLeft, localTop);
            txtBoxKey.Name = txtName;
            txtBoxKey.Size = new System.Drawing.Size(width, 21);
        }

        private void btnAddHeader_Click(object sender, EventArgs e)
        {
            AddTextBox(ref AddHeaderTimes, this.tPageHeader, "txtHeader", 197);
        }

        private void btnAddParamFixed_Click(object sender, EventArgs e)
        {
            AddTextBox(ref AddParamTimes, this.tPageRequestRound, "txtParam", 62);
        }

        //private void btnAddParamRange_Click(object sender, EventArgs e)
        //{
        //    AddParamTimes++;
        //    AddTextBoxControl(AddParamTimes, this.tPageRequestRound,
        //        "txtParam" + AddParamTimes + "Key", 135, 9, 35 + AddParamTimes * 27);
        //    AddTextBoxControl(AddParamTimes, this.tPageRequestRound,
        //        "txtParam" + AddParamTimes + "ValueMin", 180, 150, 35 + AddParamTimes * 27);
        //    AddTextBoxControl(AddParamTimes, this.tPageRequestRound,
        //        "txtParam" + AddParamTimes + "ValueMax", 180, 340, 35 + AddParamTimes * 27);
        //}

        //private void btnAddParamArray_Click(object sender, EventArgs e)
        //{
        //    AddParamTimes++;
        //    AddTextBoxControl(AddParamTimes, this.tPageRequestRound,
        //        "txtParam" + AddParamTimes + "Key", 135, 9, 35 + AddParamTimes * 27);
        //    AddTextBoxControl(AddParamTimes, this.tPageRequestRound,
        //        "txtParam" + AddParamTimes + "ValueArray", 360, 150, 35 + AddParamTimes * 27);
        //}

        private void btnRootAddChild_Click(object sender, EventArgs e)
        {
            int total = 0;
            foreach (Control ctl in this.pnlFields.Controls)
            {
                if (ctl.Name.StartsWith("labTrees0_"))
                    total++;
            }

            if (total >= 50)
            {
                MessageBox.Show("最多可设置50个");
                return;
            }

            Label labTree = new Label();
            TextBox txtTreeNode = new TextBox();
            TextBox txtTreeFiled = new TextBox();
            TextBox txtTreeKey = new TextBox();
            Button btnAddChilds = new Button();
            this.pnlFields.Controls.Add(labTree);
            this.pnlFields.Controls.Add(txtTreeNode);
            this.pnlFields.Controls.Add(txtTreeFiled);
            this.pnlFields.Controls.Add(txtTreeKey);
            this.pnlFields.Controls.Add(btnAddChilds);


            labTree.Location = new System.Drawing.Point(3, 39 + 29 * total);
            labTree.Name = "labTrees0_" + total;
            labTree.Size = new System.Drawing.Size(29, 12);
            labTree.Text = "┗--";


            txtTreeNode.Location = new System.Drawing.Point(38, 35 + 29 * total);
            txtTreeNode.Name = "txtTreeNodes0_" + total;
            txtTreeNode.Size = new System.Drawing.Size(200, 21);


            txtTreeKey.Location = new System.Drawing.Point(244, 35 + 29 * total);
            txtTreeKey.Name = "txtTreeKeys0_" + total;
            txtTreeKey.Size = new System.Drawing.Size(100, 21);


            txtTreeFiled.Location = new System.Drawing.Point(350, 35 + 29 * total);
            txtTreeFiled.Name = "txtTreeFileds0_" + total;
            txtTreeFiled.Size = new System.Drawing.Size(100, 21);


            btnAddChilds.Location = new System.Drawing.Point(456, 34 + 29 * total);
            btnAddChilds.Name = "btnAddChilds0_" + total;
            btnAddChilds.Size = new System.Drawing.Size(75, 23);
            btnAddChilds.Text = "添加下级";
            btnAddChilds.UseVisualStyleBackColor = true;
            btnAddChilds.Click += new System.EventHandler(this.btnAddChild_Click);
        }

        private void btnAddChild_Click(object sender, EventArgs e)
        {
            Button button = (Button)sender;

            string flag = button.Name.Substring(12);
            string[] flags = flag.Split('_');
            int level = flags.Count() - 1;
            int height = button.Location.Y;//控件位置y值

            int total = 1;
            int totalRow = 0;
            List<string> addFlags = new List<string>();
            foreach (Control ctl in this.pnlFields.Controls)
            {
                if (ctl.Name.StartsWith("labTree"))
                {
                    totalRow++;
                    string lblFlag = ctl.Name.Substring(8);
                    if (lblFlag.StartsWith(flag + "_") && ctl.Name.Length < (flag.Length + 12))
                        total++;

                    string[] lblFlags = lblFlag.Split('_');
                    for (int i = 0; i < lblFlags.Length; i++)
                    {
                        if (Convert.ToInt32(lblFlags[i]) >= Convert.ToInt32(flags[i]))
                        {
                            if (lblFlags[i] != flags[i])
                            {
                                Console.WriteLine("下移控件：" + lblFlag);
                                addFlags.Add(lblFlag);
                                break;
                            }
                            else if (i == flags.Length - 1)
                            {
                                if (height < ctl.Location.Y)
                                    height = ctl.Location.Y;
                                break;
                            }
                        }
                        else//小
                        {
                            break;
                        }
                    }
                }
            }
            Console.WriteLine("total:" + total);
            if (totalRow >= 50)
            {
                MessageBox.Show("最多可设置50个");
                return;
            }
            foreach (Control ctl in this.pnlFields.Controls)
            {
                string item = addFlags.FirstOrDefault(s => ctl.Name.EndsWith("s" + s));
                if (item != null)
                {
                    ctl.Location = new Point(ctl.Location.X, ctl.Location.Y + 29);
                }
            }

            Label labTree = new Label();
            TextBox txtTreeNode = new TextBox();
            TextBox txtTreeFiled = new TextBox();
            TextBox txtTreeKey = new TextBox();
            Button btnAddChilds = new Button();
            this.pnlFields.Controls.Add(labTree);
            this.pnlFields.Controls.Add(txtTreeNode);
            this.pnlFields.Controls.Add(txtTreeFiled);
            this.pnlFields.Controls.Add(txtTreeKey);
            this.pnlFields.Controls.Add(btnAddChilds);


            labTree.Location = new System.Drawing.Point(3 + 30 * level, height + 29);
            labTree.Name = "labTrees" + flag + "_" + total;
            labTree.Size = new System.Drawing.Size(29, 12);
            labTree.Text = "┗--";


            txtTreeNode.Location = new System.Drawing.Point(38 + 30 * level, height - 4 + 29);
            txtTreeNode.Name = "txtTreeNodes" + flag + "_" + total;
            txtTreeNode.Size = new System.Drawing.Size(200, 21);


            txtTreeKey.Location = new System.Drawing.Point(244 + 30 * level, height - 4 + 29);
            txtTreeKey.Name = "txtTreeKeys" + flag + "_" + total;
            txtTreeKey.Size = new System.Drawing.Size(100, 21);


            txtTreeFiled.Location = new System.Drawing.Point(350 + 30 * level, height - 4 + 29);
            txtTreeFiled.Name = "txtTreeFileds" + flag + "_" + total;
            txtTreeFiled.Size = new System.Drawing.Size(100, 21);


            btnAddChilds.Location = new System.Drawing.Point(456 + 30 * level, height - 5 + 29);
            btnAddChilds.Name = "btnAddChilds" + flag + "_" + total;
            btnAddChilds.Size = new System.Drawing.Size(75, 23);
            btnAddChilds.Text = "添加下级";
            btnAddChilds.UseVisualStyleBackColor = true;
            btnAddChilds.Click += new System.EventHandler(this.btnAddChild_Click);
        }

        private void btnSee_Click(object sender, EventArgs e)
        {
            Dictionary<string, string> dicParams = new Dictionary<string, string>();
            Dictionary<string, string> dicHeaders = new Dictionary<string, string>();
            List<string> listRangeParams = new List<string>();
            GetHeaderAndParams(out dicHeaders, out dicParams, out listRangeParams);


            //请求地址方式
            string strUrl = "";
            Method method = Method.Get;
            if (tabControl1.SelectedIndex == 0)//循环
            {
                strUrl = txtUrl.Text;
                if (cbbMethod.SelectedIndex != 0)
                    method = Method.Post;
                dicParams.Add(txtParamRangeKey.Text, listRangeParams[0]);
            }
            else if (tabControl1.SelectedIndex == 1) { }//数据库
            else { }//文本


            Form formShowHtml = new ShowHtmlStr(strUrl, dicParams, dicHeaders, method);
            formShowHtml.Show();
        }

        private void btnCrawler_Click(object sender, EventArgs e)
        {
            List<CrawlerFields> listField = GetCrawlerList();

            Dictionary<string, string> dicParams = new Dictionary<string, string>();
            Dictionary<string, string> dicHeaders = new Dictionary<string, string>();
            List<string> listRangeParams = new List<string>();
            GetHeaderAndParams(out dicHeaders, out dicParams, out listRangeParams);

            //请求地址方式
            string strUrl = "";
            Method method = Method.Get;
            if (tabControl1.SelectedIndex == 0)//循环
            {
                strUrl = txtUrl.Text;
                if (cbbMethod.SelectedIndex != 0)
                    method = Method.Post;
            }
            else if (tabControl1.SelectedIndex == 1) { }//数据库
            else { }//文本

            new CommonCrawler(0, 1, dicParams, dicHeaders, method).Crawler(new List<string>() { strUrl }, txtParamRangeKey.Text, listRangeParams, listField, "", "");
        }

        public List<CrawlerFields> GetCrawlerList()
        {
            List<CrawlerFields> listField = new List<CrawlerFields>();
            foreach (Control item in this.pnlFields.Controls)
            {
                if (item.Name.StartsWith("txtTreeNodes"))
                {
                    string path = item.Name.Substring(12);
                    var model = GetCrawlerField(listField, path);
                    model.Node = item.Text;
                }
                else if (item.Name.StartsWith("txtTreeFileds"))
                {
                    string path = item.Name.Substring(13);
                    var model = GetCrawlerField(listField, path);
                    model.Field = item.Text;
                }
                else if (item.Name.StartsWith("txtTreeKeys"))
                {
                    string path = item.Name.Substring(11);
                    var model = GetCrawlerField(listField, path);
                    model.Key = item.Text;
                }
            }
            return listField;
        }

        private CrawlerFields GetCrawlerField(List<CrawlerFields> listField, string path)
        {
            var model = listField.FirstOrDefault(s => s.Path == path);
            if (model == null)
            {
                model = new CrawlerFields();
                model.Path = path;
                model.PathLength = path.Split('_').Count();
                listField.Add(model);
            }
            return model;
        }

        public void GetHeaderAndParams(out Dictionary<string, string> dicHeaders, out Dictionary<string, string> dicParams, out List<string> listRangeParams)
        {
            dicHeaders = new Dictionary<string, string>();
            dicParams = new Dictionary<string, string>();
            listRangeParams = new List<string>();

            dicHeaders.Add("timeout", txtHeaderTimeout.Text);
            dicHeaders.Add("contentType", txtHeaderContentType.Text);
            dicHeaders.Add("host", txtHeaderHost.Text);
            dicHeaders.Add("accept", txtHeaderAccept.Text);
            dicHeaders.Add("connection", txtHeaderConnection.Text);
            dicHeaders.Add("referer", txtHeaderReferer.Text);
            dicHeaders.Add("userAgent", txtHeaderUserAgent.Text);
            foreach (Control ctl in this.tPageHeader.Controls)
            {
                if (ctl.Name.StartsWith("txtHeader") && ctl.Name.EndsWith("Key"))
                {
                    if (string.IsNullOrWhiteSpace(ctl.Text) == false)
                    {
                        foreach (Control ctl2 in this.Controls)
                        {
                            if (ctl2.Name.Equals(ctl.Name.Replace("Key", "Value")))
                            {
                                dicHeaders.Add(ctl.Text, ctl2.Text);
                                continue;
                            }
                        }
                    }
                }
            }
            if (tabControl1.SelectedIndex == 0)
            {
                foreach (Control ctl in this.tPageRequestRound.Controls)
                {
                    if (ctl.Name != "txtParamRangeKey" && ctl.Name.StartsWith("txtParam") && ctl.Name.EndsWith("Key"))
                    {
                        if (string.IsNullOrWhiteSpace(ctl.Text) == false)
                        {
                            string nameValue = ctl.Name.Replace("Key", "Value");
                            foreach (Control ctl2 in this.Controls)
                            {
                                if (ctl2.Name.Equals(nameValue))
                                {
                                    dicParams.Add(ctl.Text, ctl2.Text);
                                }
                            }
                        }
                    }
                }

                if (string.IsNullOrWhiteSpace(txtParamRangeKey.Text) == false)
                {
                    if (cbbParamType.SelectedIndex == 1 && string.IsNullOrWhiteSpace(txtParamArray.Text) == false)
                    {
                        listRangeParams.AddRange(txtParamArray.Text.Split(','));
                    }
                    else if (string.IsNullOrWhiteSpace(txtParamMin.Text) == false)
                    {
                        if (string.IsNullOrWhiteSpace(txtParamMax.Text) == false)
                        {
                            int minValue = 0;
                            int maxValue = 0;

                            if (int.TryParse(txtParamMin.Text, out minValue) && int.TryParse(txtParamMax.Text, out maxValue))
                            {
                                if (minValue < maxValue)
                                {
                                    var list = Enumerable.Range(minValue, maxValue - minValue + 1);
                                    listRangeParams.AddRange(list.Select(s => s.ToString()));
                                }
                                else
                                    listRangeParams.Add(txtParamMin.Text);
                            }
                        }
                        else
                            listRangeParams.Add(txtParamMin.Text);
                    }
                }
            }
        }

        private void cbbParamType_SelectedIndexChanged(object sender, EventArgs e)
        {
            if (cbbParamType.SelectedIndex == 1)
            {
                txtParamMin.Hide();
                txtParamMax.Hide();
                txtParamArray.Show();
            }
            else
            {
                txtParamMin.Show();
                txtParamMax.Show();
                txtParamArray.Hide();
            }
        }

        private void btnAddTable_Click(object sender, EventArgs e)
        {

        }

        private void txtSaveToDb_TextChanged(object sender, EventArgs e)
        {
            cbbSaveToTable.Items.Clear();
        }

        private void txtSaveToDb_Leave(object sender, EventArgs e)
        {
            if (cbbSaveToTable.Items.Count == 0 && string.IsNullOrWhiteSpace(txtSaveToDb.Text) == false)
            {
                try
                {
                    DataTable dt = new BLL.BLLSQLInfo().GetTable(txtSaveToDb.Text);
                    cbbSaveToTable.Items.AddRange(dt.AsEnumerable().Select(s => s["name"]).ToArray());
                    cbbSaveToTable.SelectedIndex = 0;
                }
                catch (Exception ex)
                {
                    Common.Msg.Log.GetLog.Warn("获取数据库表信息失败", this.GetType(), ex);
                    MessageBox.Show(ex.Message);
                }
            }
        }

        private void btnRefreshRequestTable_Click(object sender, EventArgs e)
        {
            try
            {
                cbbRequestTable.Items.Clear();
                if (string.IsNullOrWhiteSpace(txtRequestFromDB.Text) == false)
                {
                    DataTable dt = new BLL.BLLSQLInfo().GetTable(txtRequestFromDB.Text);
                    cbbRequestTable.Items.AddRange(dt.AsEnumerable().Select(s => s["name"]).ToArray());
                    cbbRequestTable.SelectedIndex = 0;
                }
            }
            catch (Exception ex)
            {
                Common.Msg.Log.GetLog.Warn("获取数据库表信息失败", this.GetType(), ex);
                MessageBox.Show(ex.Message);
            }
        }

        private void btnRefreshRequestField_Click(object sender, EventArgs e)
        {
            try
            {
                cbbRequestField.Items.Clear();
                if (string.IsNullOrWhiteSpace(txtRequestFromDB.Text) == false && string.IsNullOrWhiteSpace(cbbRequestTable.SelectedText))
                {
                    DataTable dt = new BLL.BLLSQLInfo().GetColumns(txtRequestFromDB.Text, cbbRequestTable.SelectedText);
                    cbbRequestField.Items.AddRange(dt.AsEnumerable().Select(s => s["ColumnName"]).ToArray());
                    cbbRequestField.SelectedIndex = 0;
                }
            }
            catch (Exception ex)
            {
                Common.Msg.Log.GetLog.Warn("获取数据库表字段信息失败", this.GetType(), ex);
                MessageBox.Show(ex.Message);
            }

        }
    }
}
